﻿using System;
using System.Collections.Generic;
using System.Text;

namespace NORM
{
    /// <summary>
    /// 
    /// </summary>
    public class Enumerable
    {
        public static IEnumerable<T> Where<T>(Func<T, bool> predicate, IEnumerable<T> source)
        {
            foreach (T item in source)
            {
                if (predicate(item))
                {
                    yield return item;
                }
            }
        }

        public static IEnumerable<TResult> Select<T, TResult>(Func<T, TResult> selector, IEnumerable<T> source)
        {
            foreach (T item in source)
            {
                yield return selector(item);
            }
        }

        public static List<T> ToList<T>(IEnumerable<T> source)
        {
            List<T> list = new List<T>();
            foreach (T item in source)
            {
                list.Add(item);
            }

            return list;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>    
    public class Enumerable<T>
    {
        private IEnumerable<T> m_source;

        public Enumerable(IEnumerable<T> source)
        {
            if (source == null) throw new ArgumentNullException("source");
            this.m_source = source;
        }

        public Enumerable<T> Where(Func<T, bool> predicate)
        {
            if (predicate == null) throw new ArgumentNullException("predicate");
            return new Enumerable<T>(Where(this.m_source, predicate));
        }

        private static IEnumerable<T> Where(IEnumerable<T> source, Func<T, bool> predicate)
        {
            foreach (T item in source)
            {
                if (predicate(item))
                {
                    yield return item;
                }
            }
        }

        public Enumerable<TResult> Select<TResult>(Func<T, TResult> selector)
        {
            if (selector == null) throw new ArgumentNullException("selector");
            return new Enumerable<TResult>(Select(this.m_source, selector));
        }

        private static IEnumerable<TResult> Select<TResult>(IEnumerable<T> source, Func<T, TResult> selector)
        {
            foreach (T item in source)
            {
                yield return selector(item);
            }
        }

        public List<T> ToList()
        {
            List<T> list = new List<T>();
            foreach (T item in m_source)
            {
                list.Add(item);
            }
            return list;
        } 

    }
}
